SQL ServerのUPDATE文でWHERE句がない場合に警告を出したい
UPDATEをテーブルの全件にかけたくなることってそんなにない
全件UPDATEしたい時もある
「全レコードのXX列をYYで初期化したい」とか
全件更新しようとしてたら警告してほしい
WHERE 1とか入っていると無力かもしれない…
とりあえず公式
この辺にないだろうか
なぜそれが必要なのですか?
間違えてやっちゃうから
私は先にSELECT文を作成してからWHERE句より前をUPDATE文に書き換えます
それをやっていて、1テーブルだけすり抜けちゃったから困っている
間違えた手順
1. テーブルがある
table:sample_table
id name address_id
1 A 1
2 B 1
3 C 34
4 D 47
5 E 47
...
50 ZZZ 47
2. id = 3のレコードのaddress_idを5にしたい
3. SELECT文を組み立てる
code:確認用.sql
SELECT * FROM sample_table WHERE id = 3;
table:result
id name address_id
3 C 34
4. UPDATE文に書き直す
上で作成したSELECT(確認用.sql)を書き換えてUPDATEにする…のをミスる
code:本来実行したい.sql
UPDATE sample_table set address_id = 5 WHERE id = 3;
code:間違えた.sql
UPDATE sample_table set address_id = 5; -- WHEREがない
5. 間違えた.sqlを実行後、確認用.sqlを実行する
code:まとめる.sql
BEGIN TRANSACTION;
SELECT * FROM sample_table WHERE id = 3; -- 確認用.sqlからコピー
UPDATE sample_table set address_id = 5; -- WHEREがない
SELECT * FROM sample_table WHERE id = 3; -- 確認用.sqlからコピー
ROLLBACK;
table:result_before
id name address_id
3 C 34
table:result_after
id name address_id
3 C 5
id = 3は変わっているが、それ以外も全部変わっている…
6. これを「修正したい対象は変わっているからOK」として実行してしまう(COMMITしてしまう)…
8. どうするか
解決方法
何が一番良いのかわからない
どうすれば気づけるか?
code:まとめる.sql
BEGIN TRANSACTION;
SELECT * FROM sample_table WHERE id = 3;
UPDATE sample_table set address_id = 5;
SELECT @@ROWCOUNT; -- UPDATEの直後で取得
SELECT * FROM sample_table WHERE id = 3;
ROLLBACK;
table:result_before
id name address_id
3 C 34
table:rowcount
_COLUMN1
50
table:result_after
id name address_id
3 C 5
修正するレコードは1件のはずで、SELECTだと正しく1件表示されているのに、UPDATE直後の@@ROWCOUNTが1じゃないのはおかしい code:まとめる.sql
BEGIN TRANSACTION;
SELECT * FROM sample_table WHERE id = 3;
UPDATE sample_table set address_id = 5 OUTPUT deleted.address_id, inserted.address_id;
SELECT * FROM sample_table WHERE id = 3;
ROLLBACK;
table:result_before
id name address_id
3 C 34
table:output
address_id address_id_1
1 5
1 5
34 5
47 5
47 5
... ...
47 5
table:result_after
id name address_id
3 C 5
修正するレコードは1件のはずだが、UPDATEの結果address_idが変わりまくっていることがわかる
insertの場合
code:まとめる.sql
BEGIN TRANSACTION;
insert into sample_table (id, name, address_id) output inserted.* values (51, 'Z', 40);
ROLLBACK;
table:output
id name address_id
51 Z 40
参考
ログ
書いた記憶はあったけど辿り着くのに時間がかかった
OUTPUT句を見に来た(2024/10/21)